load("//tools/install:install.bzl", "install", "install_files")
load(
    "//tools/skylark:pybind.bzl",
    "drake_pybind_library",
    "get_drake_py_installs",
    "get_pybind_package_info",
)
load(
    "//tools/skylark:drake_py.bzl",
    "drake_py_binary",
    "drake_py_library",
    "drake_py_unittest",
)
load("@python//:version.bzl", "PYTHON_SITE_PACKAGES_RELPATH")
load(
    "//tools/workspace:cmake_configure_file.bzl",
    "cmake_configure_file",
)
load("//bindings/pydrake:pydrake.bzl", "add_lint_tests_pydrake")

package(default_visibility = [
    "//bindings/pydrake:__subpackages__",
])

# This determines how `PYTHONPATH` is configured, and how to install the
# bindings.
PACKAGE_INFO = get_pybind_package_info("//bindings")

drake_pybind_library(
    name = "visualization",
    cc_deps = [
        "//bindings/pydrake:documentation_pybind",
        "//bindings/pydrake/common:default_scalars_pybind",
        "//bindings/pydrake/common:serialize_pybind",
    ],
    cc_so_name = "__init__",
    cc_srcs = [
        "visualization_py.cc",
        "visualization_py_config.cc",
        "visualization_py_image_systems.cc",
        "visualization_py_sliders.cc",
        "visualization_py.h",
    ],
    package_info = PACKAGE_INFO,
    py_data = [
        "_rgbd_camera_sliders.dmd.yaml",
        "_rgbd_camera_sliders.sdf",
    ],
    py_deps = [
        "//bindings/pydrake/multibody",
        "//bindings/pydrake/planning",
        "//bindings/pydrake/solvers",
        "//bindings/pydrake/systems",
        "//bindings/pydrake/geometry",
        "//bindings/pydrake:lcm_py",
        "//lcmtypes:lcmtypes_drake_py",
    ],
    py_srcs = [
        "meldis.py",
        "model_visualizer.py",
        "_meldis.py",
        "_model_visualizer.py",
        "_plotting.py",
        "_triad.py",
        "_video.py",
        "_visualization_extra.py",
    ],
)

drake_py_binary(
    name = "meldis",
    srcs = ["meldis.py"],
    visibility = ["//tools:__pkg__"],
    deps = [":visualization"],
)

drake_py_binary(
    name = "model_visualizer",
    srcs = ["model_visualizer.py"],
    data = ["//:all_models"],
    visibility = ["//tools:__pkg__"],
    deps = [":visualization"],
)

drake_py_binary(
    name = "lcm_image_array_viewer",
    srcs = ["_lcm_image_array_viewer.py"],
    deps = [":visualization"],
)

# TODO(jwnimmer-tri) For now, this is a private library for testing only. Once
# Meldis needs this it should move up into the main "visualization" library.
drake_py_library(
    name = "_lcm_image_array_viewer_py",
    srcs = ["_lcm_image_array_viewer.py"],
    deps = [":visualization"],
)

cmake_configure_file(
    name = "generate_run_installed_meldis",
    src = "run_installed_meldis.py.in",
    out = "run_installed_meldis.py",
    defines = [
        "PYTHON_SITE_PACKAGES_RELPATH=" + PYTHON_SITE_PACKAGES_RELPATH,
    ],
)

cmake_configure_file(
    name = "generate_run_installed_model_visualizer",
    src = "run_installed_model_visualizer.py.in",
    out = "run_installed_model_visualizer.py",
    defines = [
        "PYTHON_SITE_PACKAGES_RELPATH=" + PYTHON_SITE_PACKAGES_RELPATH,
    ],
)

install_files(
    name = "install_wrapper_scripts",
    dest = "bin",
    files = [
        "run_installed_meldis.py",
        "run_installed_model_visualizer.py",
    ],
    rename = {
        "bin/run_installed_meldis.py": "meldis",
        "bin/run_installed_model_visualizer.py": "model_visualizer",
    },
)

install_files(
    name = "install_models",
    dest = "share/drake/bindings/pydrake/visualization",
    files = [
        "_rgbd_camera_sliders.dmd.yaml",
        "_rgbd_camera_sliders.sdf",
    ],
)

PY_LIBRARIES = [
    ":visualization",
]

install(
    name = "install",
    install_tests = [
        ":test/visualization_install_tests.py",
    ],
    targets = [":visualization"],
    py_dest = PACKAGE_INFO.py_dest,
    deps = get_drake_py_installs(PY_LIBRARIES) + [
        ":install_models",
        ":install_wrapper_scripts",
    ],
)

drake_py_unittest(
    name = "config_test",
    deps = [
        ":visualization",
    ],
)

drake_py_unittest(
    name = "image_systems_test",
    deps = [
        ":visualization",
        "//bindings/pydrake/common/test_utilities:numpy_compare_py",
    ],
)

drake_py_unittest(
    name = "meldis_test",
    data = [
        "//examples/hydroelastic/spatula_slip_control:models",
        "//multibody/benchmarks/acrobot:models",
        "//multibody/meshcat:models",
    ],
    deps = [
        ":visualization",
    ],
)

drake_py_unittest(
    name = "model_visualizer_test",
    timeout = "moderate",
    data = [
        ":model_visualizer",
        "//manipulation/util:test_models",
        "//multibody/benchmarks/acrobot:models",
    ],
    deps = [
        ":model_visualizer",
    ],
)

drake_py_unittest(
    name = "model_visualizer_reload_test",
    data = [
        ":model_visualizer",
        "//geometry:meshcat_websocket_client",
        "//multibody/benchmarks/acrobot:models",
    ],
    flaky = True,
    deps = [
        ":model_visualizer",
    ],
)

drake_py_unittest(
    name = "model_visualizer_camera_test",
    flaky = True,
    deps = [
        ":model_visualizer",
    ],
)

drake_py_unittest(
    name = "plotting_test",
    deps = [
        ":visualization",
    ],
)

drake_py_unittest(
    name = "sliders_test",
    deps = [
        ":visualization",
    ],
)

drake_py_unittest(
    name = "triad_test",
    data = [
        "//multibody/benchmarks/acrobot:models",
    ],
    deps = [
        ":visualization",
    ],
)

drake_py_unittest(
    name = "video_test",
    size = "medium",
    deps = [
        ":visualization",
        "//bindings/pydrake/common/test_utilities:numpy_compare_py",
    ],
)

drake_py_unittest(
    name = "lcm_image_array_viewer_test",
    deps = [
        ":_lcm_image_array_viewer_py",
    ],
)

drake_py_unittest(
    name = "multicam_scenario_test",
    # Note: It's safe to use lcm in the test because it uses a non-default URL
    # and only transmits status messages.
    allow_network = ["lcm:meshcat"],
    data = [
        "test/multicam_scenario.yaml",
        "//examples/hardware_sim:hardware_sim_py",
    ],
)

add_lint_tests_pydrake(
    python_lint_extra_srcs = [
        "run_installed_meldis.py.in",
        "run_installed_model_visualizer.py.in",
        "test/visualization_install_tests.py",
    ],
)
